package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.config.chain.MetaWalletUrlConfig;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.metaWalletDTO.*;
import com.sc.nft.entity.vo.metaWalletDTO.request.CheckCollectionMetaWalletNumerberRequest;
import com.sc.nft.entity.vo.metaWalletDTO.request.CrossTransferReceiveRequest;
import com.sc.nft.entity.vo.metaWalletDTO.request.NotLinkCollectionPageRequest;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.MetaWalletService;
import com.sc.nft.service.UserCollectionService;
import com.sc.nft.sup.MetaPage;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import com.sc.nft.util.EncryptionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class MetaWalletServiceImpl implements MetaWalletService {


    private final DigitalCollectionDao digitalCollectionDao;
    private final CollecionLinkContrastRecordsDao collecionLinkContrastRecordsDao;
    private final TransferCollectionWithoutRecordsDao transferCollectionWithoutRecordsDao;
    private final CollectionChainInitDetailsLogDao collectionChainInitDetailsLogDao;
    private final UserChainInfoDao userChainInfoDao;
    private final UserInfoDao userInfoDao;
    @Autowired
    private  UserCollectionService userCollectionService;

    @Override
    public PageResult<OfferToMetaCollectionPageDTO> getNotLinkCollectionPage(NotLinkCollectionPageRequest request) throws IllegalAccessException {
        EncryptionUtil.encryptObject(request);
        String result =
        HttpRequest.post(
                StrUtil.format(
                    "{}{}", MetaWalletUrlConfig.URL, "/admin/collection/offerToMetaCollectionPage"))
            .body(JSONUtil.toJsonStr(request))
            .execute()
            .body();

        JSONObject jsonObject = JSONObject.parseObject(result);
        if(!jsonObject.get("code").equals(0)){
            throw new GlobalRunTimeException(StrUtil.format("钱包系统异常:{}",jsonObject.get("message")));
        }
        PageResult<OfferToMetaCollectionPageDTO> pageResult = JSONObject.parseObject(result, PageResult.class);
        JSONArray jsonArray = JSONUtil.parseArray(JSONObject.toJSONString(pageResult.getData()));
        EncryptionUtil.decryptJSONArray(jsonArray);
        pageResult.setData(jsonArray.toList(OfferToMetaCollectionPageDTO.class));
        return pageResult;
    }

    @Override
    public void linkCollection(CollecionLinkContrastRecords collecionLinkContrastRecords) {
        DigitalCollection collection = digitalCollectionDao.getById(collecionLinkContrastRecords.getCollectionId());
        Assert.notNull(collection, ()->new GlobalRunTimeException("藏品不存在"));

        CollecionLinkContrastRecords linckContrastRecords = collecionLinkContrastRecordsDao.getOneByLinkCollectionId(collecionLinkContrastRecords.getLinkCollectionId());
        if(ObjectUtil.isNotNull(linckContrastRecords) //如果要关联的藏品已存在记录表中,并且不是修改 则不让关联
                && Long.valueOf( collecionLinkContrastRecords.getLinkCollectionId()) != Long.valueOf(collecionLinkContrastRecords.getLinkCollectionId())){

            throw new GlobalRunTimeException(StrUtil.format("{}:已关联:{}",linckContrastRecords.getLinkCollectionName(),linckContrastRecords.getCollectionName()));
        }

        //删除
        collecionLinkContrastRecordsDao.deleteByCollectionId(collection.getId().toString());

        collecionLinkContrastRecords.setCollectionName(collection.getFirstTitle());
        collecionLinkContrastRecords.setCollectionImg(collection.getCreationContent());
        collecionLinkContrastRecords.setCollectionId(collection.getId());
        collecionLinkContrastRecords.setSumCount(collection.getSumCount());
        collecionLinkContrastRecords.setIssuePrice(collection.getIssuePrice());
        collecionLinkContrastRecords.insert();
    }

    @Override
    public CollecionLinkContrastRecords getLinkCollectionInfo(Long collectionId) {
        CollecionLinkContrastRecords collecionLinkContrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(collectionId);
        Assert.notNull(collecionLinkContrastRecords, ()->new GlobalRunTimeException("此藏品暂未关联玛特钱包藏品"));
        return collecionLinkContrastRecords;
    }

    @Override
    public Page<AdminLinkCollectionPageVO> getLinkCollectionPage(String collectionName,String linkCollectionName,Page page) {
        return collecionLinkContrastRecordsDao.getLinkCollectionPage(page, collectionName, linkCollectionName);
    }

    @Override
    public MetaWalletCrossUserVO checkUeerArrd(String userAddr) throws IllegalAccessException {
        CheckMetaWalletUeerArrdRequest request = new CheckMetaWalletUeerArrdRequest();
        request.setUserAddr(userAddr);
        EncryptionUtil.encryptObject(request);
        String metaWalletResult = HttpRequest.post(StrUtil.format("{}{}", MetaWalletUrlConfig.CHAIN_URL,"/metaChain/transferCollectionCheckUser"))
                .body(JSONUtil.toJsonStr(request))
                .execute().body();
        Result result = JSONObject.parseObject(metaWalletResult, Result.class);

        Assert.isTrue(ObjectUtil.isNotNull(result) && result.getCode() == 0, () -> new GlobalRunTimeException("地址不存在"));

        MetaWalletCrossUserVO metaWalletCrossUserVO = JSONObject.parseObject(JSONUtil.toJsonStr(result.getData()), MetaWalletCrossUserVO.class);
        EncryptionUtil.decryptObject(metaWalletCrossUserVO);
        return metaWalletCrossUserVO;
    }

    @Override
    public Boolean checkCollectionNumerber(UserInfo user,Long collectionId, List<Integer> tokenIds,String toUserAddr) throws IllegalAccessException {

        UserChainInfo userChainInfo = userChainInfoDao.getByUserId(user.getId());
        CollecionLinkContrastRecords contrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(collectionId);
        CheckCollectionMetaWalletNumerberRequest request = new CheckCollectionMetaWalletNumerberRequest();
        request.setHandleId(UUID.fastUUID().toString().replaceAll("-", ""));
        request.setCollectionId(String.valueOf(contrastRecords.getLinkCollectionId()));
        request.setFromUserAddress(userChainInfo.getAddress());
        request.setToUserAddress(toUserAddr);
        request.setTokenIds(tokenIds.toString());
        EncryptionUtil.encryptObject(request);
        log.info(JSONUtil.toJsonStr(request));
        log.info(StrUtil.format("{}{}", MetaWalletUrlConfig.CHAIN_URL,"/metaChain/transferCollectionCheck"));
        String metaWalletResult = HttpRequest.post(StrUtil.format("{}{}", MetaWalletUrlConfig.CHAIN_URL,"/metaChain/transferCollectionCheck"))
                .body(JSONUtil.toJsonStr(request))
                .execute().body();

        Result result = JSONObject.parseObject(metaWalletResult, Result.class);
        if(ObjectUtil.isNotNull(result) && result.getCode() == 0){
            Boolean data = (Boolean) result.getData();
            if(data){
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transferToMetaWallet(Long userCollectionChainLogId) throws IllegalAccessException {
        //获取钱包藏品id
        //传入编号和tokenid执行转增
        TransferCollectionWithoutRecords transferCollectionWithoutRecords = transferCollectionWithoutRecordsDao.getOneByUserCollectionChainLogIdAndStatus(userCollectionChainLogId, TransferCollectionWithoutStatusEnum.SUCCESS);

        CrossTransferReceiveRequest request = new CrossTransferReceiveRequest();
        request.setHandleId(String.valueOf(transferCollectionWithoutRecords.getId()));
        request.setTokenId(String.valueOf(transferCollectionWithoutRecords.getTokenId()));

        CollecionLinkContrastRecords contrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(transferCollectionWithoutRecords.getCollectionId());
        request.setCollectionId(String.valueOf(contrastRecords.getLinkCollectionId()));
        request.setFromUserAddress(String.valueOf(transferCollectionWithoutRecords.getFromUserAddr()));
        request.setToUserAddress(String.valueOf(transferCollectionWithoutRecords.getToUserAddr()));
        EncryptionUtil.encryptObject(request);
        String result = HttpRequest.post(StrUtil.format("{}{}", MetaWalletUrlConfig.CHAIN_URL,"/metaChain/transferCollection2Mtt"))
                .body(JSONUtil.toJsonStr(request))
                .execute().body();

        JSONObject jsonObject = JSONObject.parseObject(result);
        String code = jsonObject.getString("code");
        if(code.equals("0")){
            //转增成功
            transferCollectionWithoutRecordsDao.updateStatusById(transferCollectionWithoutRecords.getId(),TransferCollectionWithoutStatusEnum.WALLET_SUCCESS,result);
        }else {
            //转增失败
            transferCollectionWithoutRecordsDao.updateStatusById(transferCollectionWithoutRecords.getId(),TransferCollectionWithoutStatusEnum.WALLET_FAIL,result);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transferCollectonFromMetaWallet(Long collectionId, Integer tokenId, String toUserAddress, String fromUserAddress,String fromUserNickName) {

        CollecionLinkContrastRecords contrastRecords = collecionLinkContrastRecordsDao.getOneByCollectionId(collectionId);
        Assert.notNull(contrastRecords, ()->new GlobalRunTimeException("藏品未关联"));

        //校验目标用户
        UserChainInfo userChainInfo = userChainInfoDao.getByAddr(toUserAddress);
        Assert.notNull(userChainInfo, ()->new GlobalRunTimeException("目标用户不存在"));

        //校验藏品
        DigitalCollection collection = digitalCollectionDao.getById(collectionId);
        Assert.notNull(collection, ()->new GlobalRunTimeException("藏品不存在"));

        //校验藏品在仓库的状态
        CollectionChainInitDetailsLog chainInitDetailsLog = collectionChainInitDetailsLogDao.getOneByCollectionIdAnTokenIdAndStatsAndDealStatus(collectionId, tokenId, UserChainLogStatusEnum.SUCCESS);
        Assert.notNull(chainInitDetailsLog, ()->new GlobalRunTimeException("藏品不在可交易状态"));

        //给用户添加藏品
        userCollectionService.addCollection(userChainInfo.getUserId(),1L,collection.getId(), IdUtil.getSnowflakeNextIdStr(),collection.getCreationContent(),collection.getLevel(),collection.getFirstTitle(),
                collection.getUserCreatorId(), ReceivedCollectionType.TRANSFER_FROM_META_WALLET,null,null,null,Boolean.TRUE,0L,0L,0L,collection.getIssuePrice(),tokenId,null,null, AddCollectionEnum.DEFAULT,fromUserAddress,fromUserNickName,false);


    }

    @Override
    public MetaWalletCrossUserVO checkUserAddrIsExist(String userAddr) throws IllegalAccessException {
        //校验目标用户
        UserChainInfo userChainInfo = userChainInfoDao.getByAddr(userAddr);
        Assert.notNull(userChainInfo, ()->new GlobalRunTimeException("目标用户不存在"));
        UserInfo user = userInfoDao.getById(userChainInfo.getUserId());
        Assert.notNull(user, ()->new GlobalRunTimeException("目标用户不存在"));

        MetaWalletCrossUserVO metaWalletCrossUserVO = new MetaWalletCrossUserVO();
        metaWalletCrossUserVO.setUserId(user.getId().toString());
        metaWalletCrossUserVO.setUserAddr(userAddr);
        metaWalletCrossUserVO.setUrl(user.getAvatarImg());
        metaWalletCrossUserVO.setNickname(user.getNickName());

        EncryptionUtil.encryptObject(metaWalletCrossUserVO);
        return metaWalletCrossUserVO;
    }

    @Override
    public void checkCollecton(Long collectionId, List<Integer> tokenIds) {
        Assert.isFalse(tokenIds.size() > 10, ()->new GlobalRunTimeException("token id不能超过10个"));
        //校验藏品
        DigitalCollection collection = digitalCollectionDao.getById(collectionId);
        Assert.notNull(collection, ()->new GlobalRunTimeException("藏品不存在"));

        //校验藏品在仓库的状态
        Assert.isTrue(collectionChainInitDetailsLogDao.getOneByCollectionIdsAnTokenIdAndStatsAndDealStatus(collectionId, tokenIds, UserChainLogStatusEnum.SUCCESS), ()->new GlobalRunTimeException("藏品不在可交易状态"));
    }

    @Override
    public Page<ToMetaCollectionPageDTO> toWalletNotLinkCollectionPage(String daoName, String collectioName, Page page) {
        return digitalCollectionDao.toWalletNotLinkCollectionPage(daoName, collectioName, page);
    }
}
